package com.gopay.bis.hxbc.ebank.operation;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.exception.GopayException;

/**
 * 将交易信息发送到银行
 * 
 * @SocketTransport4HXBC.java
 * @author lilili
 */
public class SocketTransport4HXBC {
	private static Logger logger = LoggerFactory
			.getLogger(SocketTransport4HXBC.class);

	/** socket客户端 ***/

	private String socketip;
	private int transport;
	private int signverifyport;
	private int timeout;
	private int receiveBufferSize;
	private int sendBufferSize;
	private static String url;
	private static final String newline = "\r\n";

	public SocketTransport4HXBC() {

	}

	/***
	 * 发送签名请求
	 * 
	 * @throws IOException
	 * @throws UnknownHostException
	 * @throws SocketException
	 * @throws SocketTimeoutException
	 */
	public Object submitSignReq(String message) throws GopayException,
			UnknownHostException, IOException {
		BaseMessage baseMessage = new BaseMessage();
		baseMessage.setOutStlmCd(BankConstants.BANK_LOGO_HXBC); // 为了区分日志输出
		Socket socketClient = null;
		BufferedWriter bw = null;
		OutputStreamWriter ow = null;
		StringBuffer stringBuffer = new StringBuffer();
		String returnMessage = "";
		try {
			socketClient = this.getSocketPort(signverifyport);
			if (socketClient != null) {
				int bodyLen = message.getBytes().length;
				StringBuffer sb = new StringBuffer();
				String postUrl = "POST HTTP://" + socketip
						+ "/servlet/ABC95599.Trans HTTP/1.0";
				String sendType = "INFOSEC_SIGN";
				String s = this.getReqHeader(postUrl, sendType, 0, bodyLen);
				sb.append(s);
				sb.append(message);
				logger.info("submitSignReq:message***********===="
						+ sb.toString());
				ow = new OutputStreamWriter(socketClient.getOutputStream());
				bw = new BufferedWriter(ow);
				bw.write(sb.toString());
				bw.flush();
				// 接收返回内容，根据文档直接是个字符串
				InputStream in = socketClient.getInputStream();
				BufferedInputStream buf = new BufferedInputStream(in);
				byte[] buffer = new byte[1024];
				int iRead;
				while ((iRead = buf.read(buffer)) != -1) {
					stringBuffer.append(new String(buffer, 0, iRead, "UTF-8"));
				}
				String signMessage = stringBuffer.toString();
				logger.info("submitSignReq:signMessage***********===="
						+ signMessage);
				String[] str2 = signMessage.split("\r\n\r\n");
				returnMessage = str2[1].toString();
			}
			return returnMessage;
		} catch (Exception e) {
			BankLogUtils.printB2CSignExceptionLog(baseMessage, e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6029);
		} finally {
			if (bw != null) {
				try {
					bw.close();
				} catch (IOException e) {
					BankLogUtils.printB2CSignExceptionLog(baseMessage, e);
					throw new GopayException(
							ProcCodeConstants.PROC_CODE_100E6029);
				}
			}
			if (ow != null) {
				try {
					ow.close();
				} catch (IOException e) {
					BankLogUtils.printB2CSignExceptionLog(baseMessage, e);
					throw new GopayException(
							ProcCodeConstants.PROC_CODE_100E6029);
				}
			}
		}
	}

	/***
	 * 验签
	 * 
	 * @throws GopayException
	 */
	public Object submitverify(String message) throws GopayException {
		BaseMessage baseMessage = new BaseMessage();
		baseMessage.setOutStlmCd(BankConstants.BANK_LOGO_HXBC); // 为了区分日志输出
		Socket socketClient = null;
		BufferedWriter bw = null;
		OutputStreamWriter ow = null;
		StringBuffer stringBuffer = new StringBuffer();
		String returnMessage = "";
		try {
			socketClient = this.getSocketPort(signverifyport);
			if (socketClient != null) {
				int bodyLen = message.getBytes().length;
				StringBuffer sb = new StringBuffer();
				String postUrl = "POST HTTP://" + socketip
						+ "/servlet/ABC95599.Trans HTTP/1.0";
				String sendType = "INFOSEC_VERIFY_SIGN";
				String s = this.getReqHeader(postUrl, sendType, 0, bodyLen);
				sb.append(s);
				sb.append(message);
				ow = new OutputStreamWriter(socketClient.getOutputStream());
				bw = new BufferedWriter(ow);
				bw.write(sb.toString());
				bw.flush();
				// 接收返回内容，根据文档直接是个字符串
				BufferedReader reader = new BufferedReader(
						new InputStreamReader(socketClient.getInputStream()));
				String msg = "";
				while ((msg = reader.readLine()) != null) {
					stringBuffer.append(msg);
				}
				returnMessage = stringBuffer.toString().substring(
						stringBuffer.toString().indexOf('<'));
				if (returnMessage.indexOf('&') >= 0) {
					returnMessage = returnMessage.replaceAll("&", "&amp;");
				}
			}
			return returnMessage;
		} catch (Exception e) {
			BankLogUtils.printB2CSignExceptionLog(baseMessage, e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6029);
		} finally {
			if (bw != null) {
				try {
					bw.close();
				} catch (IOException e) {
					BankLogUtils.printB2CSignExceptionLog(baseMessage, e);
					throw new GopayException(
							ProcCodeConstants.PROC_CODE_100E6029);
				}
			}
			if (ow != null) {
				try {
					ow.close();
				} catch (IOException e) {
					BankLogUtils.printB2CSignExceptionLog(baseMessage, e);
					throw new GopayException(
							ProcCodeConstants.PROC_CODE_100E6029);
				}
			}
		}
	}

	/**
	 * 发送后返回响应信息
	 * 
	 * @param message
	 * @return
	 * @throws GopayException
	 */
	public Object submitSignReqSecond(String message) throws GopayException {
		BaseMessage baseMessage = new BaseMessage();
		baseMessage.setOutStlmCd(BankConstants.BANK_LOGO_HXBC); // 为了区分日志输出
		Socket socketClient = null;
		BufferedWriter bw = null;
		OutputStreamWriter ow = null;
		StringBuffer stringBuffer = new StringBuffer();
		String returnMessage = "";
		try {
			socketClient = getSocketPort(transport);
			if (socketClient != null) {
				int bodyLen = message.getBytes().length;

				// 提交报文
				ow = new OutputStreamWriter(socketClient.getOutputStream());
				bw = new BufferedWriter(ow);
				StringBuffer sb = new StringBuffer();
				String postUrl = "POST " + url + " HTTP/1.0";
				String sendType = "INFOSEC_SIGN";
				String s = this.getReqHeader(postUrl, sendType, signverifyport,
						bodyLen);
				sb.append(s);
				sb.append(message);
				logger.info("submitSignReqSecond:message====" + sb.toString());
				bw.write(sb.toString());
				bw.flush();
				// 接收返回内容，根据文档直接是个字符串
				InputStream in = socketClient.getInputStream();
				BufferedInputStream buf = new BufferedInputStream(in);
				byte[] buffer = new byte[1024];
				int iRead;
				while ((iRead = buf.read(buffer)) != -1) {
					stringBuffer.append(new String(buffer, 0, iRead, "UTF-8"));
				}
				String signMessage = stringBuffer.toString();
				logger.info("submitSignReqSecond:signMessage====" + signMessage);
				String[] str2 = signMessage.split("\r\n\r\n");
				if (str2[0].indexOf("200 OK") >= 0) {
					returnMessage = str2[1].toString();
				}
			}
			return returnMessage;
		} catch (Exception e) {
			BankLogUtils.printB2CSignExceptionLog(baseMessage, e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6029);
		} finally {
			if (bw != null) {
				try {
					bw.close();
				} catch (IOException e) {
					BankLogUtils.printB2CSignExceptionLog(baseMessage, e);
					throw new GopayException(
							ProcCodeConstants.PROC_CODE_100E6029);
				}
			}
			if (ow != null) {
				try {
					ow.close();
				} catch (IOException e) {
					BankLogUtils.printB2CSignExceptionLog(baseMessage, e);
					throw new GopayException(
							ProcCodeConstants.PROC_CODE_100E6029);
				}
			}
		}
	}

	/**
	 * 与银行换取连接socket
	 * 
	 * @return
	 * @throws IOException
	 * @throws UnknownHostException
	 * @throws GopayException
	 */
	private Socket getSocketPort(int port) throws GopayException,
			UnknownHostException, IOException {
		Socket socket = null;
		socket = new Socket(socketip, port);
		socket.setSoTimeout(timeout);
		socket.setReceiveBufferSize(receiveBufferSize);
		socket.setSendBufferSize(sendBufferSize);
		return socket;
	}

	/**
	 * 拼装公共报文头
	 * 
	 * @param postUrl
	 *            ,sendType
	 * @return
	 * 
	 */
	private String getReqHeader(String postUrl, String sendType, int signport,
			int bodyLen) {
		StringBuffer sb = new StringBuffer();
		sb.append(postUrl);
		sb.append(newline);
		sb.append("Accept:image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*");
		sb.append(newline);
		sb.append("Referer: HTTP://" + socketip + "/personRACrtLY.htm");
		sb.append(newline);
		sb.append("Accept-Language: zh-cn");
		sb.append(newline);
		sb.append("Content-Type: " + sendType + "/1.0");
		sb.append(newline);
		sb.append("Proxy-Connection: Keep-Alive");
		sb.append(newline);
		sb.append("User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
		sb.append(newline);
		if (signport == 0) {
			sb.append("Host: " + socketip);
		} else {
			sb.append("Host: " + socketip + ":" + signport);
		}
		sb.append(newline);
		sb.append("Content-Length: " + bodyLen);
		sb.append(newline);
		sb.append("Pragma: no-cache");
		sb.append(newline);
		sb.append(newline);
		return sb.toString();

	}

	public void setSocketip(String socketip) {
		this.socketip = socketip;
	}

	public void setTransport(int transport) {
		this.transport = transport;
	}

	public void setSignverifyport(int signverifyport) {
		this.signverifyport = signverifyport;
	}

	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}

	public void setReceiveBufferSize(int receiveBufferSize) {
		this.receiveBufferSize = receiveBufferSize;
	}

	public void setSendBufferSize(int sendBufferSize) {
		this.sendBufferSize = sendBufferSize;
	}

	public static void setUrl(String url) {
		SocketTransport4HXBC.url = url;
	}
}
